/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.maze.Population;

import java.util.ArrayList;
import org.maze.configuration.IndividualConfiguration;
import org.maze.individual.Individual;

/**
 *
 * @author tpasquie
 */
public class Population {
    private ArrayList<Village> villages = new ArrayList<Village>();
    private int generation=0;
    private double averageScore;
    private double averageDiversity;
    private Individual fitest;


    public Population(IndividualConfiguration indivConf, int size, int nbVillage) throws Exception{
        for(int i = 0; i < nbVillage; i++){
            villages.add(new Village(indivConf, size));
        }
    }

    public void ComputeStats(){
        averageScore=0;
        averageDiversity=0;
        for(Village v : villages){
            averageScore+=v.getAverageScore();
            averageDiversity+=v.getAverageDiversity();
        }
        averageScore/=villages.size();
        averageDiversity/=villages.size();
    }

    public void nextGeneration() throws Exception{
        generation++;

        if(generation%100==0 && villages.size() > 1){
            System.out.println("Number of villages : "+villages.size());
            ArrayList<Individual> villagers = new ArrayList<Individual>();
            for(Village v : villages){
                villagers.addAll(v.getVillagers());
            }
            System.out.println("Total pop size : "+villagers.size());
            int nbVillage = villages.size()-1;
            int villageSize = villagers.size()/nbVillage - 1;
            villages = new ArrayList<Village>();
            for(int i = 0; i < nbVillage; i++){
                ArrayList<Individual> villPop = new ArrayList<Individual>();
                for(int j=i*villageSize; j < (i+1)*villageSize; j++){
                    villPop.add(villagers.get(j));
                }
                villages.add(new Village(villPop));
            }
            System.out.println("Number of villages : "+villages.size());
            System.out.println("Population Size of Village : "+villages.get(0).getSize());
        }
        Thread[] t = new Thread[villages.size()];
        int i = 0;
        for(Village v : villages){
            t[i] = v.getThread();
            t[i].start();
            i++;
        }

        for(i = 0; i < t.length; i++){
            t[i].join();
        }
        this.ComputeStats();
        Individual f = villages.get(0).getFitest();
        for(int ii=1; ii<villages.size(); ii++){
            if(f.getFitnessScore() < villages.get(ii).getFitest().getFitnessScore())
                f = villages.get(ii).getFitest();
        }
        this.fitest = (Individual)f.clone();
    }

    
    
    public double getAverageDiversity(){
        return averageDiversity;
    }
    
    public double getAverageScore(){
        return averageScore;
    }

    public int getGeneration() {
        return generation;
    }

    public Individual getFitest() {        
        return fitest;
    }


}
